package com.liyuncong.algorithm.algorithm_similarity.util;

import java.util.BitSet;

import com.liyuncong.algorithm.algorithm_similarity.entity.Vector;

public class VectorUtil {
	/**
	 * 验证两个向量的长度（向量维度）是否相等，
	 * @param vector1
	 * @param vector2
	 */
	public static void validateVectorLength(Vector vector1, Vector vector2) {
		int vectorLength = vector1.getLength();
		if (vectorLength != vector2.getLength()) {
			throw new IllegalArgumentException("vector1's length"
					+ vectorLength + "is not equal to the vector2's "
					+ "length:" + vector2.getLength());
		}
	}
	
	/**
	 * 计算向量的长度
	 * @param vector 向量
	 * @return
	 */
	public static float computeVectorSize(Vector vector) {
		float[] vector1 = vector.getVector();
		return computeVectorSize(vector1);
	}
	
	public static float computeVectorSize(float[] vector) {
		int vectorLength = vector.length;
		// 向量分量的平方和
		float quadraticSum = 0;
		for(int i = 0; i < vectorLength; i++) {
			float element = vector[i];
			float elementSquare = (float) Math.pow(element, 2);
			quadraticSum += elementSquare;
		}
		return (float) Math.sqrt(quadraticSum);
	}
	
	/**
	 * 计算两个向量的点乘；
	 * 计算过程优化1：只有两个向量相同位置的元素都非0的时候才相乘
	 * 
	 * @param vector1
	 * @param vector2
	 * @return
	 */
	public static float dotProduct(Vector vector1, Vector vector2) {
		BitSet bitSet1 = vector1.getBitSet();
		BitSet bitSet2 = vector2.getBitSet();
		bitSet1.and(bitSet2);
		int vectorLength = vector1.getLength();
		float sum = 0f;
		for(int i = 0; i < vectorLength; i++) {
			// 只有两个向量i位置的元素都非0时，才有必要相乘
			if (bitSet1.get(i)) {
				float product = vector1.valueOf(i) * vector2.valueOf(i);
				sum += product;

			}
		}
		return sum;
	}
	
	/**
	 * 生成一个BitSet，当vector中索引为i的元素不是0时，BitSet
	 * 对应位置被设置为1
	 * @param vector
	 * @return
	 */
	public static BitSet getIndexsOfNonzero(Vector vector) {
		return getIndexsOfNonzero(vector.getVector());
	}
	
	/**
	 * 通过数组生成Bitset，数组中不为0的元素对应的Bitset中的
	 * 位置被置位
	 * @param vector
	 * @return
	 */
	public static BitSet getIndexsOfNonzero(float[] vector) {
		int vectorLength = vector.length;
		BitSet bitSet = new BitSet(vectorLength);
		for(int i = 0; i < vectorLength; i++) {
			if (vector[i] != 0) {
				bitSet.set(i);
			}
		}
		return bitSet;
	}
	
	/**
	 * 生成与传入Bitset一样的另一个Bitset
	 * @param bitSet
	 * @return
	 */
	public static BitSet copyBitSet(BitSet bitSet) {
		int bitsetLength = bitSet.length();
		BitSet copyBitSet = new BitSet();
		for(int i = 0; i < bitsetLength; i++) {
			if (bitSet.get(i)) {
				copyBitSet.set(i);
			}
		}
		return copyBitSet;
	}
	
	/**
	 * 获得Bitset中非零元素个数
	 * @param bitSet
	 * @return
	 */
	public static int getNumofNonzero(BitSet bitSet) {
		int num = 0;
		int bitsetLength = bitSet.length();
		for(int i = 0; i < bitsetLength; i++) {
			if (bitSet.get(i)) {
				num++;
			}
		}
		return num;
	}
}
